using Microsoft.EntityFrameworkCore;
using WeatherSystem.API.Data;
using WeatherSystem.API.Models;
using WeatherSystem.API.Services;
using WeatherSystem.API.Hubs;

namespace WeatherSystem.API.Services
{
    /// <summary>
    /// 数据采集服务接口
    /// </summary>
    public interface IDataCollectionService
    {
        Task CollectWeatherDataAsync();
        Task<bool> IsCollectionEnabledAsync();
        Task SetCollectionStatusAsync(bool enabled);
        Task<DateTime?> GetLastCollectionTimeAsync();
    }

    /// <summary>
    /// 数据采集服务实现
    /// </summary>
    public class DataCollectionService : IDataCollectionService
    {
        private readonly ILogger<DataCollectionService> _logger;
        private readonly IConfiguration _configuration;
        private readonly IServiceProvider _serviceProvider;

        public DataCollectionService(
            ILogger<DataCollectionService> logger,
            IConfiguration configuration,
            IServiceProvider serviceProvider)
        {
            _logger = logger;
            _configuration = configuration;
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 采集天气数据
        /// </summary>
        public async Task CollectWeatherDataAsync()
        {
            var startTime = DateTime.UtcNow;
            var notificationService = _serviceProvider.GetService<IWeatherNotificationService>();
            var logEntry = new DataCollectionLog
            {
                Id = Guid.NewGuid(),
                CityId = null, // 系统级日志，不关联特定城市
                Status = "Running",
                Message = "开始数据采集",
                ExecutionTime = startTime
            };

            try
            {
                using var scope = _serviceProvider.CreateScope();
                var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
                context.DataCollectionLogs.Add(logEntry);
                await context.SaveChangesAsync();

                _logger.LogInformation("开始天气数据采集任务");

                // 推送数据采集开始通知
                if (notificationService != null)
                {
                    await notificationService.NotifyDataCollectionStartAsync();
                }

                // 检查采集是否启用
                if (!await IsCollectionEnabledAsync())
                {
                    _logger.LogWarning("数据采集已禁用，跳过本次采集");
                    await UpdateLogEntryAsync(logEntry, "Skipped", "数据采集已禁用", 0);
                    return;
                }

                // 获取所有启用自动采集的城市
                using var cityScope = _serviceProvider.CreateScope();
                var cityContext = cityScope.ServiceProvider.GetRequiredService<WeatherDbContext>();
                var cities = await cityContext.Cities
                    .Where(c => c.IsActive && c.AutoCollectEnabled)
                    .ToListAsync();

                if (!cities.Any())
                {
                    _logger.LogWarning("没有找到启用的城市，跳过数据采集");
                    await UpdateLogEntryAsync(logEntry, "Completed", "没有启用的城市", 0);
                    return;
                }

                int successCount = 0;
                int errorCount = 0;
                var errors = new List<string>();

                // 为每个城市采集数据
                foreach (var city in cities)
                {
                    try
                    {
                        await CollectCityWeatherDataAsync(city, notificationService!);
                        successCount++;
                        _logger.LogDebug("城市 {CityName} 数据采集成功", city.Name);
                    }
                    catch (Exception ex)
                    {
                        errorCount++;
                        var errorMsg = $"城市 {city.Name} 数据采集失败: {ex.Message}";
                        errors.Add(errorMsg);
                        _logger.LogError(ex, "城市 {CityName} 数据采集失败", city.Name);
                    }
                }

                // 更新最后采集时间
                await UpdateLastCollectionTimeAsync();

                // 更新日志
                var status = errorCount == 0 ? "Completed" : "Partial";
                var message = $"采集完成，成功: {successCount}, 失败: {errorCount}";
                if (errors.Any())
                {
                    message += $"\n错误详情: {string.Join("; ", errors)}";
                }

                await UpdateLogEntryAsync(logEntry, status, message, successCount);

                // 推送数据采集完成通知
                if (notificationService != null)
                {
                    await notificationService.NotifyDataCollectionCompleteAsync(successCount, errorCount);
                }

                _logger.LogInformation("天气数据采集任务完成，成功: {SuccessCount}, 失败: {ErrorCount}",
                    successCount, errorCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "数据采集任务执行失败");
                await UpdateLogEntryAsync(logEntry, "Failed", $"采集任务失败: {ex.Message}", 0);
                throw;
            }
        }

        /// <summary>
        /// 采集单个城市的天气数据（EAV结构）
        /// </summary>
        private async Task CollectCityWeatherDataAsync(City city, IWeatherNotificationService notificationService)
        {
            // 调用天气API
            using var weatherScope = _serviceProvider.CreateScope();
            var weatherApiService = weatherScope.ServiceProvider.GetRequiredService<IWeatherApiService>();
            var apiResponse = await weatherApiService.GetCurrentWeatherAsync(
                city.Latitude, city.Longitude);

            // 创建EAV天气数据记录
            var weatherDataEntry = new WeatherDataEntry
            {
                CityId = city.Id,
                RecordedAt = DateTime.UtcNow,
                Source = "API"
            };

            using var cityScope = _serviceProvider.CreateScope();
            var cityContext = cityScope.ServiceProvider.GetRequiredService<WeatherDbContext>();
            
            // 获取活跃的指标定义
            var metricDefinitions = await cityContext.MetricDefinitions
                .Where(m => m.IsActive)
                .ToListAsync();

            // 创建动态指标值
            var metricValues = new List<MetricValue>();
            var apiData = new Dictionary<string, object>
            {
                ["temperature"] = apiResponse.Temperature,
                ["humidity"] = apiResponse.Humidity,
                ["pressure"] = apiResponse.Pressure,
                ["windSpeed"] = apiResponse.WindSpeed,
                ["windDirection"] = apiResponse.WindDirection,
                ["visibility"] = apiResponse.Visibility,
                ["uvIndex"] = apiResponse.UVIndex,
                ["weatherCondition"] = apiResponse.WeatherCondition ?? "Unknown"
            };

            foreach (var metricDef in metricDefinitions)
            {
                if (apiData.TryGetValue(metricDef.Key, out var value))
                {
                    metricValues.Add(new MetricValue
                    {
                        WeatherDataEntryId = weatherDataEntry.Id,
                        MetricKey = metricDef.Key,
                        RawValue = value?.ToString() ?? string.Empty,
                        DataType = metricDef.DataType
                    });
                }
            }

            weatherDataEntry.Metrics = metricValues;
            cityContext.WeatherDataEntries.Add(weatherDataEntry);
            await cityContext.SaveChangesAsync();

            // 转换为字典格式推送
            var weatherDataDict = new Dictionary<string, object>
            {
                ["id"] = weatherDataEntry.Id,
                ["cityId"] = weatherDataEntry.CityId,
                ["cityName"] = city.Name,
                ["recordedAt"] = weatherDataEntry.RecordedAt,
                ["source"] = weatherDataEntry.Source
            };
            
            foreach (var metric in metricValues)
            {
                weatherDataDict[metric.MetricKey] = ConvertRawValueToTyped(metric.RawValue, metric.DataType);
            }

            // 推送实时天气数据更新
            if (notificationService != null)
            {
                await notificationService.NotifyWeatherUpdateAsync(weatherDataDict);
            }

            _logger.LogDebug("城市 {CityName} 天气数据已保存，温度: {Temperature}°C",
                city.Name, apiResponse.Temperature);
        }

        /// <summary>
        /// 检查数据采集是否启用
        /// </summary>
        public async Task<bool> IsCollectionEnabledAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
            var config = await context.SystemConfigurations
                .FirstOrDefaultAsync(c => c.ConfigKey == "DataCollectionEnabled");

            //return config?.ConfigValue?.ToLower() == "true";
            return true;
        }

        /// <summary>
        /// 设置数据采集状态
        /// </summary>
        public async Task SetCollectionStatusAsync(bool enabled)
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
            var config = await context.SystemConfigurations
                .FirstOrDefaultAsync(c => c.ConfigKey == "DataCollectionEnabled");

            if (config == null)
            {
                config = new SystemConfiguration
                {
                    Id = Guid.NewGuid(),
                    ConfigKey = "DataCollectionEnabled",
                    ConfigValue = enabled.ToString().ToLower(),
                    Description = "数据采集开关",
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };
                context.SystemConfigurations.Add(config);
            }
            else
            {
                config.ConfigValue = enabled.ToString().ToLower();
                config.UpdatedAt = DateTime.UtcNow;
            }

            await context.SaveChangesAsync();
            _logger.LogInformation("数据采集状态已更新为: {Status}", enabled ? "启用" : "禁用");
        }

        /// <summary>
        /// 获取最后采集时间
        /// </summary>
        public async Task<DateTime?> GetLastCollectionTimeAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
            var config = await context.SystemConfigurations
                .FirstOrDefaultAsync(c => c.ConfigKey == "LastCollectionTime");

            if (config?.ConfigValue != null && DateTime.TryParse(config.ConfigValue, out var lastTime))
            {
                return lastTime;
            }

            return null;
        }

        /// <summary>
        /// 更新最后采集时间
        /// </summary>
        private async Task UpdateLastCollectionTimeAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();
            var config = await context.SystemConfigurations
                .FirstOrDefaultAsync(c => c.ConfigKey == "LastCollectionTime");

            var currentTime = DateTime.UtcNow;

            if (config == null)
            {
                config = new SystemConfiguration
                {
                    Id = Guid.NewGuid(),
                    ConfigKey = "LastCollectionTime",
                    ConfigValue = currentTime.ToString("O"),
                    Description = "最后数据采集时间",
                    CreatedAt = currentTime,
                    UpdatedAt = currentTime
                };
                context.SystemConfigurations.Add(config);
            }
            else
            {
                config.ConfigValue = currentTime.ToString("O");
                config.UpdatedAt = currentTime;
            }

            await context.SaveChangesAsync();
        }

        /// <summary>
        /// 更新日志条目
        /// </summary>
        private async Task UpdateLogEntryAsync(
            DataCollectionLog logEntry,
            string status,
            string message,
            int recordsProcessed)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var context = scope.ServiceProvider.GetRequiredService<WeatherDbContext>();

                var existingLog = await context.DataCollectionLogs
                    .FirstOrDefaultAsync(l => l.Id == logEntry.Id);

                if (existingLog != null)
                {
                    existingLog.Status = status;
                    existingLog.Message = message;
                    existingLog.RecordsCollected = recordsProcessed;
                    var durationMs = (DateTime.UtcNow - logEntry.ExecutionTime).TotalMilliseconds;
                    existingLog.Duration = durationMs > int.MaxValue ? int.MaxValue : (int)durationMs;

                    await context.SaveChangesAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新日志条目失败: {LogId}", logEntry.Id);
            }
        }

        /// <summary>
        /// 将原始值转换为相应的类型
        /// </summary>
        private object ConvertRawValueToTyped(string rawValue, string dataType)
        {
            return dataType.ToLower() switch
            {
                "decimal" => decimal.TryParse(rawValue, out var d) ? d : 0m,
                "int" => int.TryParse(rawValue, out var i) ? i : 0,
                "boolean" => bool.TryParse(rawValue, out var b) && b,
                _ => rawValue
            };
        }
    }

    /// <summary>
    /// 后台数据采集服务
    /// </summary>
    public class BackgroundDataCollectionService : BackgroundService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<BackgroundDataCollectionService> _logger;
        private readonly IConfiguration _configuration;
        private readonly int _intervalMinutes;

        public BackgroundDataCollectionService(
            IServiceProvider serviceProvider,
            ILogger<BackgroundDataCollectionService> logger,
            IConfiguration configuration)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            _configuration = configuration;

            // 从配置读取采集间隔，默认30分钟
            _intervalMinutes = _configuration.GetValue<int>("DATA_COLLECTION_INTERVAL_MINUTES", 30);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("后台数据采集服务启动，采集间隔: {Interval} 分钟", _intervalMinutes);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    using var scope = _serviceProvider.CreateScope();
                    var dataCollectionService = scope.ServiceProvider
                        .GetRequiredService<IDataCollectionService>();

                    await dataCollectionService.CollectWeatherDataAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "后台数据采集执行失败");
                }

                // 等待下次采集
                await Task.Delay(TimeSpan.FromMinutes(_intervalMinutes), stoppingToken);
            }

            _logger.LogInformation("后台数据采集服务已停止");
        }
    }
}